#include<iostream>
#include<functional>
#include<memory>
#include<math.h>

using std::cout;
using std::endl;
using std::function;
using std::bind;

class Figure
{
public:
    using dp=function<void ()>;
    using fp=function<double()>;
    dp _dp;
    fp _fp;
    void setDisplay(dp&& rhs)
    {
        _dp=std::move(rhs);

    }

    void setArea(fp&& rhs)
    {
        _fp=std::move(rhs);
    }
    void rundis()
    {
        if(_dp)
        {
            _dp();
        }

    }
    double runarea()
    {
        if(_fp)
        {
         return   _fp();
        }
        return 0;
    }
};
class Rectangle
{
public:

    Rectangle(double x,double y)
        :_line(x)
         ,_high(y)
    {}
    void display()
    {
        cout<<"rectangle: ";
    }
    double area()
    {
        return _line*_high;
    }
private:
    double _line;
    double _high;
};
void test(Figure &rhs)
{
    rhs.rundis();
    cout<<"   areas is "<<rhs.runarea()<<endl;
    
}
class Triangle
{
public:
    Triangle(double a,double b ,double c)
        :_a(a)
         ,_b(b)
         ,_c(c)
    {}
    void display()
    {
        cout<<"triangle:  ";
    }
    double area()
    {
        double sum=(_a+_b+_c)/2;
        return  sqrt((sum-_a)*(sum-_b)*(sum-_c)*sum);
    }

private:
    double _a;
    double _b;
    double _c;
};
class Circle
{
public:
    Circle(double r)
        :_r(r)
    {}
    void display()
    {
        cout<<"Circle:  ";
    }
    double area()
    {
        return 3.14*_r*_r;
    }
private:
    double _r ;
};
int main(void)
{
    Figure fg;
    Rectangle rec(5,6);
    Triangle tri(3,4,5);
    Circle cir(5);

    fg.setDisplay(bind(&Rectangle::display,&rec));
    fg.setArea(bind(&Rectangle::area,&rec));
    test(fg);

    fg.setDisplay(bind(&Triangle::display,&tri));
    fg.setArea(bind(&Triangle::area,&tri));
    test(fg);

    fg.setDisplay(bind(&Circle::display,&cir));
    fg.setArea(bind(&Circle::area,&cir));
    test(fg);
}
